package com.webserver.core;

import com.webserver.core.annotations.Controller;
import com.webserver.core.annotations.RequestMapping;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;

/**
 * 该类用于维护请求路劲与对应的业务处理类和方法
 */
public class HandlerMapping {
    /**
     * 当前类的每一个实例用于记录一个业务方法以及该方法所属的Controller对象
     */
    /*
    * 例如
    * key:/myweb/reg
    * value:MethodMapping{
    * Object Controller=>UserController的实例
    * Method method=>reg 方法
    * }
    * */
    private static Map<String ,MethodMapping> mapping=new HashMap<>();
    static {
        try {
            initMapping();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }
    private static void initMapping() throws ClassNotFoundException, URISyntaxException, IllegalAccessException, InstantiationException {
        /*
        * 扫描com.webserver.controller包下的所有类
        * 利用反射机制加载这些类的类对象
        * 判断该类是否使用注解@Controller标注，没有的则忽略
        * 扫描该类的所有的方法，并判断该方法是否使用注解@RequestMapping标注,没有的忽略
        * 将注解的e@RequestMapping中的参数获取到
        * */
        File file=new File(
                HandlerMapping.class.getClassLoader().getResource("./com/webserver/controller").toURI()
        );
        File[] files=file.listFiles(f->f.getName().endsWith(".class"));
        for (File f:files) {
            Class cls=Class.forName("com.webserver.controller."+f.getName().substring(0,f.getName().lastIndexOf(".")));
                if (cls.isAnnotationPresent(Controller.class)) {
                    Object obj=cls.newInstance();
                    Method[] methods = cls.getDeclaredMethods();
                    for (Method m : methods) {
                        if (m.isAnnotationPresent(RequestMapping.class)) {
                            RequestMapping requestMapping=m.getAnnotation(RequestMapping.class);
                            String req=requestMapping.value();
                            MethodMapping methodMapping=new MethodMapping(obj,m);
                            mapping.put(req,methodMapping);
                    }
                }
            }
        }
        System.out.println(mapping);
    }

    public static class MethodMapping{
        private Object controller;
        private Method method;

        @Override
        public String toString() {
            return "MethodMapping{" +
                    "controller=" + controller +
                    ", method=" + method +
                    '}';
        }

        public MethodMapping(Object controller, Method method) {
            this.controller = controller;
            this.method = method;
        }

        public Object getController() {
            return controller;
        }

        public void setController(Object controller) {
            this.controller = controller;
        }

        public Method getMethod() {
            return method;
        }

        public void setMethod(Method method) {
            this.method = method;
        }
    }

    public static void main(String[] args) {

    }
    public  static MethodMapping getMethod(String patch){
        return mapping.get(patch);
    }


}
